package com.liruo.learn.spring.mvc.enumconverter.jacksondeprecated;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.liruo.learn.spring.mvc.enumconverter.SourceEnum;

import java.io.IOException;

public class ToEnumJsonDeserializer2<S, T extends SourceEnum<S>> extends JsonDeserializer<T> implements ContextualDeserializer {

    private final Class<? extends SourceEnum<S>> enumClazz;

    @Override
    public Class<?> handledType() {
        return this.enumClazz;
    }

    public ToEnumJsonDeserializer2(Class<?> enumClazz) {
        if(!SourceEnum.class.isAssignableFrom(enumClazz)){
            throw new RuntimeException("enum must implements " + SourceEnum.class.getName());
        }
        this.enumClazz =  (Class<? extends SourceEnum<S>>)enumClazz;
    }

    @Override
    public T deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
        JsonToken currentToken = jp.getCurrentToken();
        Object source = null;
        switch (currentToken){
            case VALUE_STRING -> source = jp.getText();
            case VALUE_NUMBER_INT -> source = jp.getIntValue();
        }
        for (SourceEnum<S> enumeration : enumClazz.getEnumConstants()){
            if(enumeration.getSource().equals(source)){
                return (T)enumeration;
            }
        }
        throw new IllegalArgumentException(
                "has not the enumeration source[class="
                        + ((currentToken == JsonToken.VALUE_STRING) ? String.class.getName() : Integer.class.getName())
                        + "] value=" + source);
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctx, BeanProperty property) throws JsonMappingException {
        Class<?> rawClass = property.getType().getRawClass();
        return new ToEnumJsonDeserializer2(rawClass);
    }
}